﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Beetle.Packages
{
    public class AMF3Package:HeadSizeOfPackage
    {
        public AMF3Package()
        {
        }
        public AMF3Package(TcpChannel channel)
            : base(channel)
        {
        }
        public override object ReadCast(object message)
        {
            return ((MessageAdapter)message).Message;
        }

        public override object WriteCast(object message)
        {
            MessageAdapter adapter = new MessageAdapter();
            adapter.Message = message;
            return adapter;
        }

        protected override IMessage ReadMessageByType(BufferReader reader, out object typeTag)
        {
            typeTag = "MessageAdapter";
            return new MessageAdapter();
        }

        protected override void WriteMessageType(IMessage msg, BufferWriter writer)
        {
            
        }

        public override void MessageWrite(IMessage msg, BufferWriter writer)
        {
            msg.Save(writer);
        }

        public override IMessage MessageRead(BufferReader reader)
        {
            IMessage msg = null;
            object typeTag;
            msg = ReadMessageByType(reader, out typeTag);
            if (msg == null)
                throw NetTcpException.TypeNotFound(typeTag.ToString());
            try
            {
                msg.Load(reader);
            }
            catch (Exception e)
            {
                NetTcpException err = NetTcpException.ObjectLoadError(typeTag.ToString(), e);
                throw err;
            }
            return msg;
        }

        class MessageAdapter : IMessage
        {
            public object Message
            {
                get;
                set;
            }

            public void Load(BufferReader reader)
            {
                ByteArraySegment segment = ByteSegment;
                int count = reader.ReadInt32();
                reader.Read(count - 4, segment);
                using (System.IO.MemoryStream steram = new System.IO.MemoryStream(segment.Array, segment.Offset, segment.Count))
                {
                    FluorineFx.AMF3.ByteArray ba = new FluorineFx.AMF3.ByteArray(steram);
                    ba.ObjectEncoding = FluorineFx.ObjectEncoding.AMF3;
                    Message = ba.ReadObject();
                }
                
            }
            public void Save(BufferWriter writer)
            {
                ByteArraySegment segment = ByteSegment;
                using (System.IO.MemoryStream steram = new System.IO.MemoryStream(segment.Array))
                {
                    FluorineFx.AMF3.ByteArray ba = new FluorineFx.AMF3.ByteArray(steram);
                    ba.ObjectEncoding = FluorineFx.ObjectEncoding.AMF3;
                    ba.WriteObject(Message);
                    segment.SetInfo(0, (int)steram.Position);
                }
                writer.Write(segment.Count + 4);
                writer.Write(segment.Array, segment.Offset, segment.Count);
               
            }
            [ThreadStatic]
            private static ByteArraySegment mByteSegment;
            public static ByteArraySegment ByteSegment
            {
                get
                {
                    if (mByteSegment == null)
                        mByteSegment = new ByteArraySegment(TcpUtils.DataPacketMaxLength);
                    return mByteSegment;
                }
            }
        }
    }
    
}
